// Package controller @author dingrui @since 2021/11/28
package controller

import (
	"encoding/json"
	"fmt"
	"time"

	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/hero"

	"github.com/bannirui/mini-prize/common"
	"github.com/bannirui/mini-prize/dal/model"
	"github.com/bannirui/mini-prize/dal/service"
	"github.com/bannirui/mini-prize/datasource"
	"github.com/bannirui/mini-prize/web/entity/request"
	"github.com/bannirui/mini-prize/web/entity/vo"
	"github.com/bannirui/mini-prize/web/util"
	"github.com/bannirui/mini-prize/web/util/response"
)

func AdminGiftRouter(party iris.Party) {
	var (
		party_     = party.Party("/admin-gift")
		controller = AdminGiftController{}
	)
	party_.Get("/", hero.Handler(controller.Get))
	party_.Post("/edit", hero.Handler(controller.GetEdit))
	party_.Post("/", hero.Handler(controller.PostSave))
	party_.Delete("/", hero.Handler(controller.GetDelete))
	party_.Get("/reset", hero.Handler(controller.GetReset))
}

type AdminGiftController struct {
}

//
//  Get
//  @Description:
//                GET http://localhost:8080/api/mini-prize/admin-gift
//  @receiver c
//  @param ctx
//
func (c *AdminGiftController) Get(ctx iris.Context) {
	var (
		dataList     []model.Gift
		total        int
		data         model.Gift
		idx          int
		prizeData    [][2]int
		err          error
		newPrizeData []string
	)

	// 数据列表
	dataList = service.G_giftService.GetAll(false)
	// 遍历
	for idx, data = range dataList {
		// 奖品发放的计划数据
		prizeData = make([][2]int, 0)
		if err = json.Unmarshal([]byte(data.Data), &prizeData); err != nil || prizeData == nil || len(prizeData) < 1 {
			dataList[idx].Data = "[]"
		} else {
			newPrizeData = make([]string, len(prizeData))
			for i, pd := range prizeData {
				ct := common.FormatFromUnixTime(int64(pd[0]))
				newPrizeData[i] = fmt.Sprintf("[%s]:%d", ct, pd[1])
			}
			if str, err := json.Marshal(newPrizeData); err == nil || len(str) > 0 {
				dataList[idx].Data = string(str)
			} else {
				dataList[idx].Data = "[]"
			}
		}
		// 奖品当前的奖品池数量
		num := 0
		if rs, err := datasource.G_redis.Do("HGET", "gift_pool", data.Id); err != nil {
			// TODO: 2021/11/28
		} else {
			num = int(common.GetInt64(rs, 0))
		}
		dataList[idx].Name = fmt.Sprintf("[%d]%s", num, dataList[idx].Name)
	}
	total = len(dataList)
	// 构建响应
	response.Ok(ctx, response.CODE_OK, &vo.ListGiftVO{
		DataList: dataList,
		Total:    total,
	})
	return
}

//
//  GetEdit
//  @Description:
//                GET http://localhost:8080/api/mini-prize/admin-gift/edit?id=1
//  @receiver c
//  @param ctx
//
func (c *AdminGiftController) GetEdit(ctx iris.Context) {
	var (
		id       int
		giftInfo vo.ViewGiftVO
		gift     *model.Gift
	)
	id = ctx.URLParamIntDefault("id", 0)
	giftInfo = vo.ViewGiftVO{}
	if id > 0 {
		if gift = service.G_giftService.Get(id, false); gift != nil {
			giftInfo.Id = gift.Id
			giftInfo.Title = gift.Name
			giftInfo.PrizeNum = gift.TotalCnt
			giftInfo.PrizeCode = gift.HitRate
			giftInfo.PrizeTime = gift.DurationDay
			giftInfo.Img = gift.Img
			giftInfo.Displayorder = gift.DispData
			giftInfo.Gtype = gift.Type
			giftInfo.Gdata = gift.Data
			giftInfo.TimeBegin = common.FormatFromUnixTime(int64(gift.BeginTime))
			giftInfo.TimeEnd = common.FormatFromUnixTime(int64(gift.EndTime))
		}
	}
	response.Ok(ctx, response.CODE_OK, giftInfo)
}

func (c *AdminGiftController) PostSave(ctx iris.Context) {
	var (
		giftInfo model.Gift
		t1       time.Time
		t2       time.Time
		err1     error
		err2     error
	)
	// request body
	data := request.ViewGiftRequest{}
	if err := ctx.ReadJSON(data); err != nil {
		goto ERR
	}
	giftInfo = model.Gift{}
	giftInfo.Id = data.Id
	giftInfo.Name = data.Title
	giftInfo.TotalCnt = data.PrizeNum
	giftInfo.HitRate = data.PrizeCode
	giftInfo.DurationDay = data.PrizeTime
	giftInfo.Img = data.Img
	giftInfo.DispOrder = data.Displayorder
	giftInfo.Type = data.Gtype
	giftInfo.Data = data.Gdata
	t1, err1 = common.ParseTime(data.TimeBegin)
	t2, err2 = common.ParseTime(data.TimeEnd)
	if err1 != nil || err2 != nil {
		goto ERR
	}
	giftInfo.BeginTime = int(t1.Unix())
	giftInfo.EndTime = int(t2.Unix())
	if giftInfo.Id > 0 {
		dataInfo := service.G_giftService.Get(giftInfo.Id, false)
		if dataInfo != nil {
			giftInfo.GmtUpdated = int(time.Now().Unix())
			giftInfo.OpIp = common.GetClientIP(ctx.Request())
			// 对比修改的内容项
			if dataInfo.TotalCnt != giftInfo.TotalCnt {
				// 奖品总数量发生了改变
				giftInfo.RemainCnt = dataInfo.RemainCnt - dataInfo.TotalCnt - giftInfo.TotalCnt
				if giftInfo.RemainCnt < 0 || giftInfo.RemainCnt <= 0 {
					giftInfo.RemainCnt = 0
				}
				giftInfo.Status = dataInfo.Status
				util.ResetGiftPrizeData(&giftInfo)
			} else {
				giftInfo.RemainCnt = giftInfo.TotalCnt
			}
			if dataInfo.DurationDay != giftInfo.DurationDay {
				// 发奖周期发生了变化
				util.ResetGiftPrizeData(&giftInfo)
			}
			_ = service.G_giftService.Update(&giftInfo, []string{"title", "prize_num", "left_num", "prize_code", "prize_time",
				"img", "displayorder", "gtype", "gdata", "time_begin", "time_end", "sys_updated"})
		} else {
			giftInfo.Id = 0
		}
	}
	if giftInfo.Id > 0 {
		giftInfo.RemainCnt = giftInfo.TotalCnt
		giftInfo.OpIp = common.GetClientIP(ctx.Request())
		giftInfo.GmtCreated = int(time.Now().Unix())
		_ = service.G_giftService.Create(&giftInfo)
		// 更新奖品的发奖计划
		util.ResetGiftPrizeData(&giftInfo)
	}
	response.Ok(ctx, response.CODE_OK, nil)
	return
ERR:
	response.InternalServerError(ctx, response.CODE_SYS_PARSE_PARAMS_ERROR)
	return
}

func (c *AdminGiftController) GetDelete(ctx iris.Context) {
	var (
		id  int
		err error
	)
	if id, err = ctx.URLParamInt("id"); err != nil {
		goto ERR
	}
	if err = service.G_giftService.Delete(id); err != nil {
		goto ERR
	}
	response.Ok(ctx, response.CODE_OK, nil)
	return
ERR:
	response.InternalServerError(ctx, response.CODE_SYS_PARSE_PARAMS_ERROR)
	return
}

func (c *AdminGiftController) GetReset(ctx iris.Context) {
	var (
		id  int
		err error
	)
	if id, err = ctx.URLParamInt("id"); err != nil {
		goto ERR
	}
	if err = service.G_giftService.Update(&model.Gift{Id: id, Status: 0}, []string{"status"}); err != nil {
		goto ERR
	}
	response.Ok(ctx, response.CODE_OK, nil)
	return
ERR:
	response.InternalServerError(ctx, response.CODE_SYS_PARSE_PARAMS_ERROR)
	return
}
